#include "HttpServer.hpp"
#include <memory>
#include <vector>
#include "Util.hpp"
#include <string>
using namespace std;
#define SEP "\t\n" 
//"\n"也可以                                                                                    
// 一般一个webserver，不做特殊说明，如果用户之间默认访问‘/’, 我们绝对不能把把整站给对方
//  需要添加默认首页！！而且，不能让用户访问wwwroot里面的任何一个目录本身，也可以给每一个目录都带上一个默认首页！
const std::string DefaultHomePage = "index.html";
const std::string WebRoot = "./wwwroot"; // web根目录
const std::string Default_Error = "./wwwroot/Error.html";

class HttpRequest
{
public:
    HttpRequest()
        : _url(WebRoot)
    {
    }
    string _methods;        // 请求方法，例如GET,POST
    string _url;            // 请求的网址
    string _version;        // HTTP协议版本
    vector<string> _header; // 请求报头->有概率也会有请求正文
    string _suffix;         //获取网页的后缀
};

// 将收到的客户端数据进行处理，反序列化
HttpRequest RequestDeserialization(string &request)
{
    HttpRequest req;
    string line = Split(request, SEP);                               // 请求行分割出来
    AnalysisRequestLine(line, req._methods, req._url, req._version); // 将请求行解析出来，参数都是&
    while (!request.empty())
    {
        // 将报头数据一个个分割出来
        line = Split(request, SEP);
        //update
        if(line=="")
        {
            //表示Split分割失败，line为空字符串
            //直接把剩下的存起来
            //这种情况一般是为了处理客户端请求中带有有效载荷（请求正文）
            //如果是不带有效载荷的，那么就是request就是空字符串，和不加判断前是一样的结果
            req._header.push_back(request);
            break;
        }
        // 依次存起来
        req._header.push_back(line);
        
        //debug
        //cout<<request.size()<<endl;
    }
    LogMessage(Information, "Deserialization done...");
    return req;
}

// 打印解析后的HTTP请求
void Print(const HttpRequest &req)
{
    cout << "After RequestDeserialization:" << endl;
    cout << "methods:" << req._methods << endl;
    cout << "url:" << req._url << endl;
    cout << "version:" << req._version << endl;
    for (auto &e : req._header)
    {
        cout << e << endl;
    }
}

// 获取客户端获取的网页内容是什么类型的文件->.html、.txt....
void Suffix(string &url, string &target)
{
    auto pos = url.rfind(".");
    target = url.substr(pos);
}

// 资源，图片(.png, .jpg...)，网页(.html, .htm)，视频(.mp3)，音频(..)->文件！都要有自己的后缀！
string CheckType(const string &suffix)
{
    if (suffix == ".jpeg")
    {
        return "image/jpeg";
    }
    else if (suffix == ".html")
        return "text/html";
    else if (suffix == ".js")
        return "application/x-javascript";
    else if (suffix == ".png")
        return "image/png";
    else if (suffix == ".jpg")
        return "image/jpeg";
    else
    {
        return "";
    }
}

string HandlerHttp(string &request)
{
    // 打印一下客户端发来的请求
    cout << "------------------------------------------" << endl;
    cout << request << endl;
    HttpRequest req = RequestDeserialization(request); // 解析请求报文
    Print(req);
    cout << "------------------------------------------" << endl;

#define TEST 1

#ifdef TEST

    // 如果访问的是根目录，那么就访问默认首页
    // 一般访问形式为127.0.0.1:8888/
    // 或者127.0.0.1:8888/index.html
    // 不管是哪个都自带/，因此我们的webRoot不需要结尾加上/
    if (req._url[req._url.size() - 1] == '/')
    {
        req._url += DefaultHomePage;
    }

    // 接下来就是要给客户端响应了
    string body; // 读取客户端想要的网页内容->body是响应的有效载荷（响应正文）
    if (ReadFile(req._url, body) == true)
    {
        // 获取文件类型
        Suffix(req._url, req._suffix);
        // 响应报文中的状态行
        string response = "HTTP/1.0 200 OK";
        // 换行
        response += SEP;
        // 响应报文中的报头
        // 有效载荷的长度
        //以下两个报头很重要，对于比较差一点的浏览器，可能不知道正文大小或者类型，即无法解析，不过现在一般性的浏览器都没有问题
        response += "Content-Length:";
        response += to_string(body.size());
        response += SEP;
        // 有效载荷的类型
        response += "Content-Type:";
        response += CheckType(req._suffix);
        response += SEP;
        //Cookie
        response+="Set-Cookie:ww=abcd";
        response+=SEP;
        // 空行
        response += SEP;
        // 有效载荷
        response += body;
        // ret+="hello http";
        return response;
    }
    else
    {
        // 读取文件失败就返回error页面
        // 状态行
        string response = "HTTP/1.0 404 Not Found";
        response += SEP;
        // 没有响应报头，所以说直接就空行
        response += SEP;
        // 读取
        ReadFile(Default_Error, body);
        // 添加响应正文
        response += body;
        return response;
    }

#else

    // 重定向
    //添加状态行
    string response="HTTP/1.0 301 Redirect";
    response+=SEP;
    //添加响应报头
    response+="Location:https://www.baidu.com/index.html";//重定向到百度
    response+=SEP;
    response+="Set-Cookie:sessionid=12345";//设置cookie值
    response+=SEP;
    //添加空行
    response+=SEP;
    return response;
 #endif   
}



void Usage(const string &proc)
{
    cout << "Method of Use:" << proc << " serverport" << endl;
}

int main(int argc, char *argv[])
{
    // 保证能正常启动服务器
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USE_ERR);
    }

    unique_ptr<HttpServer> server(new HttpServer(atoi(argv[1]), HandlerHttp));
    // 服务器的初始化，完成通信前的基本工作
    server->Init();
    // 正式开始接受客户端，开始通信
    server->Start();

    return 0;
}
